//引入axios 核心库  第一步-----
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
//引入自定义接口  数据类型检验
import { ResultData } from "./interface";
//引入qs 
import qs from "qs";
//引入路由跳转
import router from "../router";

let config = {  //AxiosRequestConfig ->  封装好的 内置属性  需要符合里面的值 第五步---
    baseURL: '/api'
}

//利用类 来实现TS的使用  第二步=====
class HttpRequest {
    //这是类的作用域   
    //定义一个属性   这个属性需要一个类型 axios已经封装完毕  直接引入即可  第三步-----
    http: AxiosInstance
    constructor(config: AxiosRequestConfig) {//实例化类之后 这里接收参数 把人家封装好的TS要求类型 也设置 第七步----

        //实例化axios  可以通过这个类的原型使用  create 里面可以写固定属性  在这里因为用到TS 所以axios也封装完毕 第四步---
        //不传config 是第四步  设置完 constructor 里面的形参之后 传入到这里
        this.http = axios.create(config);

        //请求拦截器
        this.http.interceptors.request.use((req: any) => {
            let data = sessionStorage.getItem('userInfo');
            req.headers.authorization = data ? JSON.parse(data).token : null
            return req;
        });

        //响应拦截器
        this.http.interceptors.response.use((res: AxiosResponse):any => {
            //判断是否是登录过期
            if (res.data.msg == "请设置请求头,并携带验证字符串" || res.data.msg == "权限非法") {
                router.push('/login');
            };
            
            return res.data;
        });
    };

    //封装get方法  泛型为T  是为了Vuex仓库里面的使用 需要定义数据类型   这个函数也需要返回值  是一个Promise 这个也是需要定义数据类型
    get<T>(url: string, params?: object): Promise<ResultData<T>> {
        return this.http.get(url, { params });
    };

    //封装post方法 
    post<T>(url: string, params?: any, isFile: boolean = false): Promise<ResultData<T>> {
        let data: any;
        //如果有文件上传
        if (isFile) {
            //转化数据格式
            data = new FormData();
            for (const [k, val] of Object.entries(params)) {
                data.append(k, val);
            };
        } else {
            data = qs.stringify(params);
        }
        return this.http.post(url, params);
    }
};


//第六步----
export default new HttpRequest(config);